<?php

$userRatings = array();

include "mn_db_rating_matrix.php";
include "mn_db_thumbs.php";
include "mn_get_movie_data.php";
include "imdb_ratings.php";

function sim_pearson($p1, $p2) {
	$si = Array();
	foreach ($p1 as $movieid => $rating) {
		if (isset($p2[$movieid])) {
			$si[$movieid] = 1;
		}
	}
	
	#if they are no rating in common, return 0
	if (count($si) == 0) {
		return 0;
	}

	//sum calculations
	$n = count($si);
	$sum1 = 0;
	$sum2 = 0;
	$sumSq1 = 0;
	$sumSq2 = 0;
	$pSum = 0;
	foreach ($si as $movieid => $rating) {
		//sum of all preferences
		$sum1 += $p1[$movieid];
		$sum2 += $p2[$movieid];
		//Sum of the squares
		$sumSq1 += pow($p1[$movieid], 2);
		$sumSq2 += pow($p2[$movieid], 2);
		//Sum of the products
		$pSum +=  $p1[$movieid] * $p2[$movieid];
	}
	echo $n . "<br>"; 
	echo pow($sum1,2) / 3 . "<br>";
	//Calculate r (Pearson score)
	$num = $pSum - ($sum1 * $sum2 / floatval($n));
	$den = sqrt(($sumSq1 - pow($sum1,2) / floatval($n)) * ($sumSq2 - pow($sum2,2) / floatval($n)));
	if ($den == 0) {
		return 0;
	}

	$r = $num / $den;
	
	return $r;
	
	
	
}
	
function sim_distance($p1, $p2) {
	$si = Array();
	foreach ($p1 as $movieid => $rating) {
		if (isset($p2[$movieid])) {
			$si[$movieid] = 1;
		}
	}
	
	// If they have no rating in common, return 1
	if (count($si) == 0) return 0;
	
	$sum_of_squares = 0;
	foreach ($si as $movieid => $rating) {
		$sum_of_squares += pow($p1[$movieid] - $p2[$movieid], 2);
	}
	
	return 1 / (1 + sqrt($sum_of_squares));	
}

function calc_inner_addition($category, $value, $char_num) {
	//category coeff - Genre: 0, Director: 1, Writer: 2, Actor: 3
	switch ($category) {
		case 0: 
			$ans = 0.5 * $value;
			break;
		case 1: 
			$ans = 0.5 * $value;
			break;
		case 2: 
			$ans = 0.5 * $value;
			break;
		case 3: 
			$ans = 0.3 / ($char_num / 5 + 1) * $value;
			break;
	}
	return $ans;
	
}
function addInnerElements(&$scores, $users) {
	
    // get all user likes
    $thumbs = getThumbs($users);
    // for each movie, check likes
	foreach ($scores as $movieid => $rating){
		$moviedata = getMovieData($movieid);
		foreach ($moviedata as $category) {
			$cnt = 0;
			foreach ($category as $categoryid => $entity) {
				if (isset($thumbs[$categoryid][$entity])) {
					$scores[$movieid] += calc_inner_addition($categoryid, $thumbs[$categoryid][$entity], $cnt++);
				}
			}
		}
	}
}
    
/*function topMatches($p1, $p1members, $n) {
    global $userRatings;
    $scores = Array();
    foreach ($p1members as $member) {
        unset($userRatings[$member]);
    }
    foreach ($userRatings as $userId => $rating) {
        $scores[$userId] = sim_distance($p1, $rating);
    }
    
    arsort($scores);
    array_splice($scores, $n);
    
    //addInnerElements($scores);
    //arsort($scores);
    
    return $scores;
}	*/
    
	
function my_splice($array, $count) {
	$result = array();
	$cnt = 0;
	foreach ($array as $index => $value) {
		 if ($cnt++ > $count) break;
		 $result[$index] = $value;
	}
	return $result;
}	

function getRecommendations($p1, $p1members) {
    global $userRatings;
    $totals = Array();
    $simSums = Array();
    $rankings = Array();
    
    foreach ($p1members as $member) {
        unset($userRatings[$member]);
    }
    
    foreach ($userRatings as $userId => $rating) {
        $similarity = sim_distance($p1, $rating);
        if ($similarity > 0) {
            foreach ($rating as $movieId => $r) {
                if (!isset($p1[$movieId])) {
                    if (!isset($totals[$movieId])) $totals[$movieId] = 0;
                    $totals[$movieId] += $r * $similarity;

                    if (!isset($simSums[$movieId])) $simSums[$movieId] = 0;
                    $simSums[$movieId] += $similarity;
                }
            }
        }
    }
    
    foreach ($totals as $movieId => $total) {
        $rankings[$movieId] = $total / $simSums[$movieId];
    }
	arsort($rankings);
	$rankings = my_splice($rankings, 20);
	//addInnerElements($rankings, $p1members);
    arsort($rankings);
	
    return $rankings;
}

function mergeUsers($users) {
    global $userRatings;
    $sum = array();
    $cnt = array();
    $result = array();
    
    foreach ($users as $user) {
        if (!isset($userRatings[$user])) continue;
        foreach ($userRatings[$user] as $movieId => $rating) {
            if (!isset($sum[$movieId])) {
                $sum[$movieId] = 0;
                $cnt[$movieId] = 0;
            }
            $sum[$movieId] += $rating;
            $cnt[$movieId] += 1;
        }
    }
    
    foreach ($sum as $movieId => $movieSum) {
        $result[$movieId] = $movieSum / $cnt[$movieId];
    }
    return $result;
}

function predict($movie, $user) {
    global $userRatings;
    global $imdb_ratings;
    $sum = 0;
    $total = 0;

    foreach ($userRatings as $other => $userRating) {
        if (!isset($userRating[$movie])) continue;
        $sim = sim_distance($userRatings[$user], $userRating);
        if ($sim <= 0) continue;
        $sum += $sim * $userRating[$movie];
        $total += $sim;
    }
    
    if ($total == 0) return $imdb_ratings[$movie];
    return $sum / $total;
}

function mergeUsers2($users) {
    global $userRatings;
    $sum = array();
    $cnt = array();
    $result = array();
    $groupMovies = array();
    
    foreach ($users as $user) {
        if (!isset($userRatings[$user])) continue;
        foreach ($userRatings[$user] as $movieId => $rating) {
            $groupMovies[$movieId] = 1;
        }
    }
    
    $n = count($users);
    
    foreach ($groupMovies as $movieId => $stam) {
        if (!isset($result[$movieId])) $result[$movieId] = 0;
        foreach ($users as $user) {
            if (!isset($userRatings[$user])) continue;
            if (isset($userRatings[$user][$movieId])) {
                $toAdd = $userRatings[$user][$movieId] / $n;
            }
            else {
                $toAdd = predict($movieId, $user) / $n;
            }
            $result[$movieId] += $toAdd;
        }
    }

    return $result;
}

function suggest($p_users) {
	global $userRatings;
	$userRatings = getUserRatings($p_users);
    $userlist = explode(",", $p_users);
    $users = array();
    
    foreach ($userlist as $user) {
        if (is_numeric($user)) $users[] = $user;
    }
    
    $merged = mergeUsers2($users);
    
    return getRecommendations($merged, $users);
}

?>